package com.acme.bankclient;


import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.Console;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

public class BankClient implements Runnable {

	boolean workByScenario;
	ArrayList<String> commands;
	int commandNumber;

	public BankClient() {
		workByScenario = false;
		commands = new ArrayList<String>();
		commandNumber = 0;
	}

	public BankClient(String... args) {
		if (args.length > 0) {
			workByScenario = true;
			commands = new ArrayList<String>();
			for (String s : args) {
				commands.add(s);
			}
			commandNumber = 0;
		}
	}

	/**
	 * Opens connection, launches communication handler.
	 */
	public void run() {
		// 1. creating a socket to connect to the server
		// 2. get Input and Output streams
		try (Socket requestSocket = new Socket("localhost", 2004);
				ObjectOutputStream out = new ObjectOutputStream(requestSocket.getOutputStream());
				ObjectInputStream  in  = new ObjectInputStream(requestSocket.getInputStream()); ) {

			System.out.println("[Client] " +"Connected to localhost in port 2004");
			out.flush();
			receiveResponse(in);

			communicate(in, out);

		} catch (UnknownHostException unknownHost) {
			System.err.println("You are trying to connect to an unknown host!");
		} catch (IOException ioException) {
			ioException.printStackTrace();
		}
	}

	/**
	 * Communicates with server.
	 * @param in ObjectInputStream
	 * @throws IOException
	 */
	void communicate(ObjectInputStream in, ObjectOutputStream out) throws IOException {
		boolean mustQuit = false;
		String command = "";
		// 3: Communicating with the server
		try (BufferedReader commandIn = new BufferedReader(new InputStreamReader(System.in))) {
			do {
				if (workByScenario) {
					if (commands.size() == commandNumber+1) {
						workByScenario = false;
						System.out.println("Console input mode.");
						command = commandIn.readLine();						
					} else {
						command = commands.get(++commandNumber);
					}
				} else {
					command = commandIn.readLine();
				}
				mustQuit = processCommand(command, in, out);
				receiveResponse(in);
			} while (!mustQuit);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @param in
	 * @param message
	 * @return
	 * @throws IOException
	 */
	void receiveResponse(ObjectInputStream in) throws IOException {
		String message = "";
		try {
			message = (String) in.readObject();
		} catch (ClassNotFoundException classNot) {
			System.err.println("data received in unknown format");
		}
		System.out.println("[Client] " +"server>" + message);
	}

	/**
	 * Processes commands from user.
	 * @param command
	 * @param in
	 * @param out
	 * @return true if it's time to quit. false if must work on.
	 */
	boolean processCommand(String command, ObjectInputStream in, ObjectOutputStream out) {
		String message = "";

		message = command;
		sendMessage(message, out);

		if ("bye".equals(command)) {
			sendMessage("bye", out);
			return true;
		}
		return false;
	}

	/**
	 * Sends String message to server through ObjectOutputStream.
	 * @param msg
	 * @param out
	 */
	void sendMessage(final Object msg, ObjectOutputStream out) {
		try {
			out.writeObject(msg);
			out.flush();
			System.out.println("[Client] " +"client>" + msg);
		} catch (IOException ioException) {
			ioException.printStackTrace();
		}
	}

	public static void main(final String... args) {
		BankClient client = new BankClient(args);

		client.run();
		System.out.println("--- [Client] Terminating...");
	}

}
